/*
 * Usuario.java
 *
 * Copyright 2011 Isabella A. G. Pessoa.
 * All rights reserved.
 *
 * This file is part of Mandatory Arrest
 *
 * MandatoryArrest is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * MandatoryArrest is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with MandatoryArrest. If not, see <http://www.gnu.org/licenses/>.
 *
 * Contributors:
 * Isabella Pessoa isabella.agp at gmail.com
 * Michell Jacks michelljacks at gmail.com
 * Monica Santana monicaasc.cc at gmail.com
 */

package br.edu.ufcg.dsc.lp2.projeto.model;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map.Entry;

import java.util.Map;

import br.edu.ufcg.dsc.lp2.projeto.model.exceptions.EstabelecimentoInvalidoException;
import br.edu.ufcg.dsc.lp2.projeto.model.exceptions.NomeInvalidoException;
import br.edu.ufcg.dsc.lp2.projeto.model.exceptions.NotaInvalidaException;
import br.edu.ufcg.dsc.lp2.projeto.model.exceptions.NullParameterException;

/**
 * Representa um usuario com nome e uma colecao de opinioes sobre
 * estabelecimentos.
 * 
 * @author Isabella Pessoa isabella.agp at gmail.com
 * 
 */
public class Usuario {

	/**
	 * 
	 * Cria um novo usuario.
	 * 
	 * @param nome
	 *            Nome do usuario.
	 * 
	 * @param estabelecimentos
	 *            Um iteravel de estabelecimentos.
	 */
	public Usuario(String nome, Iterable<Estabelecimento> estabelecimentos) {

		if (nome == null) {
			throw new NomeInvalidoException("Nome nao pode ser null");
		}
		if (estabelecimentos == null) {
			throw new NullParameterException(
					"Estabelecimentos nao pode ser null");
		}

		this.nome = nome;
		opinioes = new LinkedHashMap<Estabelecimento, Integer>();
		semelhanca = 0;

		for (Estabelecimento estabelecimento : estabelecimentos) {
			this.adicionaOpiniao(estabelecimento, 0);
		}
	}

	/**
	 * Retorna o nome do usuario.
	 * 
	 * @return nome Nome do usuario.
	 */
	public String getNome() {
		return nome.toString();
	}

	/**
	 * Retorna um mapa com estabelecimento e opinioes dos usuarios sobre ele.
	 * 
	 * @return mapa Estabelecimentos x Opinioes
	 */
	public Map<Estabelecimento, Integer> getOpiniao() {
		return opinioes;
	}

	/**
	 * Retorna um inteiro com a semelhanca.
	 * @return Inteiro com o valor de semelhanca.
	 */
	public int getSemelhanca() {
		return semelhanca;
	}
	
	/**
	 * Modifica o nome de um usuario.
	 * 
	 * @param novoNome
	 *            Novo nome do usuario.
	 */
	public void setNome(String novoNome) {
		this.nome = novoNome;
	}

	/**
	 * Modifica o valor de semelhanca.
	 * @param semelhanca Novo valor.
	 */
	public void setSemelhanca(int semelhanca) {
		this.semelhanca = semelhanca;
	}
	
	/**
	 * Retorna as notas de um estabelecimento.
	 * 
	 * @param e
	 * @return opinioes
	 */
	public int getNota(Estabelecimento e) {
		if (opinioes.containsKey(e)) {
			return opinioes.get(e);
		}
		return 0;
	}

	/**
	 * Adiciona as notas de um estabelecimento.
	 * 
	 * @param estabelecimento
	 *            Um estabelecimento.
	 * @param nota
	 *            A opiniao de um usuario sobre este estabelecimento.
	 */
	public void adicionaOpiniao(Estabelecimento estabelecimento, int nota) {
		if (nota < -5 || nota > 5) {
			throw new NotaInvalidaException("Nota deve estar entre -5 e 5");
		}

		if (estabelecimento == null) {
			throw new EstabelecimentoInvalidoException(
					"Estabelecimento nao pode ser null");
		}
		opinioes.put(estabelecimento, nota);
	}
	
	/**
	 * Retorna um array com todas as opinioes de um Usuario.
	 * 
	 * @param usuario
	 *            Usuario a obter as opinioes.
	 * @return Array de inteiros com opinoes dos estabelecimentos.
	 */
	public List<Integer> listaDeOpinioes() {
		List<Integer> opiniao = new ArrayList<Integer>();
		
		Iterator<Entry<Estabelecimento, Integer>> it = opinioes.entrySet().iterator();
		while (it.hasNext()) {
			Map.Entry<Estabelecimento, Integer> voto = it.next();
			opiniao.add((Integer) voto.getValue());
		}
		return opiniao;
	}
	

	/**
	 * Nome de um usuario.
	 */
	private String nome;

	/**
	 * Mapa de um estabelecimento e as opinioes dos usuarios sobre ele.
	 */
	private Map<Estabelecimento, Integer> opinioes;
	
	/**
	 * Inteiro que representa a semelhanca de um usuario com outro (resultado do produto escalar).
	 */
	private int semelhanca;
}